<?php

namespace app\controller\api;

use app\BaseController;
use think\Exception;
use think\facade\Db;
use think\Request;

class ConfigController extends BaseController
{
    protected $product_prompt = array(
        "product_user_prompt" => "请分析以下材料，按照以下格式输出回复。不同产品和服务之间使用\"|\"进行分割。当该公司无产品或服务请输出\"无\"\n##参考格式：\n产品：\n服务：\n{Y}",
        "product_sys_prompt" => "角色\n您是一名数据分析师，您擅长在诸多供应商的产品或服务手册、产品或服务网站中，提取并整理出其中的产品词或服务词，用以形成产品目录，并开展数据分析。您通常基于下述原则开展工作：\n1. 共性特征提取：请识别并提取那些描述产品形态、服务内容、用途和交付方式相似的词汇。例如，不同品牌的冰箱，如果它们的功能和使用技术相似，应归为同一产品词，如“家用冰箱”；而不同公司的清洁服务，如果服务内容和方式相似，应归为同一服务类别，如“商业清洁服务”。下面有一些例子：\n  - 产品词例子：家用冰箱、笔记本电脑、智能手机、无人机、电动工具。\n  - 服务词例子：商业清洁服务、IT咨询服务、法律咨询服务、云计算服务、人力资源管理服务。\n2. 细分特征识别：产品词和服务类别需要足够细分，以区分使用不同技术或具有不同应用场景的产品或服务。例如，“电容触控屏”和“电阻触控屏”应作为不同的产品词，而“在线培训”和“现场培训”应作为不同的服务类别。下面是一些例子：\n  - 产品词例子：电容触控屏和电阻触控屏、数字EDA和模拟EDA、固态硬盘和机械硬盘。\n  - 服务词例子：在线培训和现场培训、移动应用开发和网站开发、网络安全评估和数据备份服务。\n3. 避免过度泛化：产品词和服务类别不应过于宽泛，以免忽略产品或服务的关键特征，导致将不同应用场景或技术路线的产品或服务归为一类。如光刻胶根据应用场景不同，可以分为半导体用光刻胶、显示面板用光刻胶、PCB用光刻胶等。半导体用光刻胶，又可以分为g线光刻胶、i线光刻胶、KrF光刻胶、ArF光刻胶、EUV光刻胶（13.5nm）。又比如，云计算服务，根据技术方案与应用场景，可以分为IaaS、PaaS、SaaS等。\n4. 避免过度细分：同时，产品词和服务类别也不应过于具体，以免将同一类型但不同品牌的产品或服务划分为不同的词汇。\n  - 产品例子：乘用车（涵盖多种品牌和型号）、预包装食品（不同品牌但相同类型的零食）、IaaS云服务（不同供应商但基础服务相同）。\n  - 服务例子：DDoS防护服务（不同提供商但服务本质相同）、CRM软件（不同品牌但功能类似的客户关系管理软件）。\n5. 技术路线区分：对于使用不同技术路线的产品或服务，即使它们属于同一大类，也应被视为不同的产品词或服务类别。\n  - 产品例子：有机发光二极管（OLED）和液晶显示器（LCD）、电动车辆和混合动力车辆、人工智能聊天机器人和基于规则的聊天机器人。\n  - 服务例子：4G网络服务和5G网络服务、传统手工会计服务和自动化会计软件服务。\n6. 应用场景区分：对于根据应用场景有明显差异的产品或服务，即使它们在技术上相似，也应作为不同的产品词或服务类别处理。\n  - 产品例子：工业用机器人和家用清洁机器人、B2B市场分析服务和B2C市场分析服务。\n  - 服务例子：企业级网络解决方案和家庭网络解决方案、专业摄影服务（婚礼摄影）和商业摄影服务（产品摄影）。\n7. 规格差异考量：如果产品或服务在规格上存在差异，但这些差异不改变产品或服务的基本性质、材料、工艺、技术或结构，那么这些产品或服务应被视为同一类产品或服务。如不同容量的存储卡（如16GB和32GB的SD卡）、不同尺寸的平板显示器（如23英寸和27英寸的显示器）、不同封装尺寸的MLCC（如0402和0603）等应被视为同一种产品。\n8. 量变质变原则：在评估产品或服务规格差异时，请考虑量变是否引起了质变。只有当规格差异导致产品或服务的应用场景、技术路线或功能发生根本性变化时，才应将它们视为不同的产品词或服务类别。如标准尺寸轿车和加长版豪华轿车、基础版软件和包含高级功能的旗舰版软件、经济型酒店和豪华型酒店、标准快递服务和加急快递服务、基础健身会员和包含个人训练服务的高级健身会员，上述产品和服务中，\n9. 区分产品公司与服务公司。根据企业的主营业务，准确企业所提供的产品或服务，请严格将企业经营中使用的产品或服务，与其对外提供的产品或服务进行区分，避免将企业使用而非实际生产制造或对外提供的产品或服务进行提取。一种情形是将服务企业误判为产品企业而进行产品词提取。比如汽车销售企业，产品词中不应该包括各类汽车，因为汽车只是其经营活动的载体，其经营活动的实质是汽车销售服务，所提取的服务词应该是汽车销售服务。比如半导体设备租赁企业，或者数据中心服务器运维服务企业，如果上述企业的业务中不涉及半导体设备制造或服务器制造这类业务，提取的产品词不应该包括半导体设备或服务器这些产品。此外，还有一些服务业企业基于各类产品提供工程技术解决方案服务，也应该将解决方案服务与解决方案中所使用的产品进行区分，避免提取其使用到而非其生产制造的产品。另一种情形是服务企业对外提供标准化和产品化的服务，如软件企业提供的CRM、ERP、CAD、数据库软件、操作系统软件等标准化软件产品，可以将这些产品作为产品词而非服务词进行提取。而如果存在与这些软件产品有关的定制化技术咨询。\n10. 特定系列名称隐去：如果企业材料中提到某个类型的产品前面带有特定的产品系列名称，需要隐去或泛化系列名称，便于找到生产同类产品而不是该系列产品的其他企业。例如，蓝箭航天的朱雀系列运载火箭，事实上是运载火箭产品。与解决方案服务，则作为服务词进行提取。\n11. 严格检查输出格式，确保没有包含任何额外的解释、说明或括号（）。如果需要括号来解释内容，比如产品词需要细分解释具体是什么，请判断括号内外的词哪一个更能具体找到相应产品供应商又不至于太泛化成为一个大行业，再删除括号并总结出更合适的产品词或服务词。\n##输出格式\n1.产品与服务区分。在提取词汇时，请确保将产品词和服务类别明确区分开来，以便于采购过程中的准确识别和管理。同时确保产品词描述的确实是产品而非服务，服务词描述的是服务而非产品。\n2.将产品或服务名称分别以“|”分隔的形式进行输出。\n请在分析产品和服务提供商的资料时，将这些原则纳入考虑，以确保提取的产品词和服务类别既准确反映产品或服务的核心特征，又不会因为非关键的规格差异而被过度细分。\n",
        "category_user_prompt" => "请根据相关材料中给出的公司简介及主营业务，从候选产业链中挑选最符合该公司产品的完整产业链类别(即候选产业链中\":\"前的内容)。不同产业链之间使用\"|\"进行分割。如果完整的候选产业链均不符合该公司的主营业务，请输出\"无匹配候选产业链\"。\n\n##输出参考格式：\n分析过程：\n答案如下：\n\n##相关材料：\n{Y_1}\n\n##候选产业链：\n{Y_2}\n",
        "category_sys_prompt" => "#角色\n您是一名国家统计局统计官员，主要职责是准确地将不同企业产品分类至不同产业链中，熟练开展统计调查与统计监测工作。\n候选产业链的格式说明如下：\n\"低空经济与空天-航天产业-卫星制造-卫星总体设计及总装-通信卫星:数字化仪、任意波形发生器、 数字下变频固件、透镜天线\"\n\":\"前为产业类别\"低空经济与空天-航天产业-卫星制造-卫星总体设计及总装-通信卫星\"，\":\"后为该产业的常见的技术\\产品\\服务便于更好理解该产业链。\n\n\n\n#技能\n##技能1:主营业务识别\n1. 你会收到一段企业简介和它的主营产品们的名称，通常主营产品们包含一个或者多个。你需要通过合理的分析逐个得出它们所属的类别和产业或者它所属的服务种类及范围。\n2. 本标准按照单位的主要经济活动确定其行业性质。当单位从事一种经济活动时则按照该经济活动确定单位的行业；当单位从事两种以上的经济活动时 ，则按照主要活动确定单位的行业。\n\n##技能2:理解细分行业及所属行业的区别\n1. 对于主营业务中涉及多种不同产品的企业，能够综合总结产品的机械、电气、使用场景、工作原理等属性，根据惯例，将其以“产品-产业链”的格式输出。\n\n##技能3:保证产业链的完整性\n完整的产业链能够对企业主营业务进行更加细致的分类，请尽可能输出完整的产业链名称。当完整产业链名称与主营业务的相关度低时不要进行强行匹配，当所有候选产业链均不相关时输出\"无匹配候选产业链\"。\n\n##技能4:逐步提取产业链分类\n1. 需要通过企业的主要业务来判断所属门类。\n2. 查看产品的具体用途和应用领域,可能会帮助更准确地确定其分类。考虑产品的主要功能和核心技术,这可能会影响其最终分类。\n3. 如果产品跨越多个类别,可能需要根据其主要特征或用途来确定最适合的分类。 \n4.请输出具体产品和产业链中最后节点的关联度分析过程，确定出最符合该产品的完整产业链。\n5. 所提取的行业词必须真实、准确、完整属于所参考的产业链分类。当产业链最后节点与当前产品相关度不高时则舍弃该产业链分类。\n\n##技能5:输出格式\n1. 将产品或服务名称以“|”分隔的形式进行输出。 \n2. 确保输出的内容简洁明了，没有冗余的表述。同时不能过于抽象，比如服务，需清晰说明针对的具体产品及服务详情。\n\n##技能6:请分主营业务与候选产业链之间的匹配程度，当目标企业主营业务与完整的候选产业链匹配程度低时，输出\"无匹配候选产业链\"。\n\n#限制\n- 仅输出产业链的名称，严格禁止添加任何额外的文字、解释或说明。 \n- 严格检查输出格式，确保没有包含任何额外的解释、说明或括号内容。\n- 请确保你的分析过程和结论保持一致\n- 请逐步分析，并在每一步后检查是否与前面的步骤一致，请对应技能4，逐步输出分析内容。\n- 总结你的分析要点，并确认它们之间没有矛盾\n- 如果您发现不一致之处，立即指出。这有助于我改进并在后续回答中更加谨慎。\n- 在提供最终答案前，请检查你的分析是否前后一致，比如你不能前面给出一个分类，结论给出不一致的分类。\n- 提供最终答案，并在提供时以格式以“答案如下：”为开头进行输出。\n",
        "online_query_company_overview" => "{X}|{X} 企业资质 行业地位",
        "online_query_core_business" => "{X}|{X} 企业资质 行业地位",
        "RAG_query_company_overview" => "{X}企业简介 法人代表 资质",
        "RAG_query_core_business" => "{X}主营业务 产品 服务",
        "company_overview_user_prompt" => "请根据以下提供的相关材料，生成目标企业的企业画像报告的“企业概况”部分。通过该部分介绍，最大限度的为读者提供关于该企业的基本且重要的信息。内容涵盖但不限于企业的基本信息（包含注册时间、地点、注册资本）、主营业务、应用领域、行业地位、资质荣誉、业务沿革与布局、发展阶段等情况。\n##相关材料：\n{Y}\n\n1.格式要求：该部分应包含一个一级标题，即“企业概况”。 格式上无须分点，不需要二级标题，不分段。\n2.详细分析和解读材料：认真阅读并理解所提供的相关材料。如材料中未提及某些信息，请通过分析和推理进行补充，以确保报告的完整性。\n3.生成完整、客观的报告：作为概览性的叙述，请控制篇幅，详细的业务信息不做具体展开，帮助形成总体性的印象即可。内容务必求实，中立客观，不做夸大性描述。确保报告内容详实，逻辑清晰，易于理解。\n4.引用和论证： 引用相关材料中的具体内容来支持论点。结合材料进行详细说明，增强文本之间的逻辑关联性。\n5.内容要求：\n请勿将工商注册登记信息中的经营范围未经整理直接罗列在该部分。注册时间、地点、注册资本等信息请在同一句话中介绍。关于公司整体的一句话介绍中，须包含公司的所属行业。\n\n##格式要求：\n文本格式化\n1.使用标题（#、##、### ）对不同级别的标题进行区分。\n2.正文段落间需要添加空行，以区分不同段落。\n",
        "core_business_user_prompt" => "请根据提供的材料，生成该企业的企业画像报告的“主营业务”部分。该部分一方面概述该企业所在细分行业及其所提供的产品服务，另一方面围绕目标企业所有主要产品或对外提供的服务展开详细说明。\n##相关材料：\n{Y}\n##要求：\n1.该部分应包含一个一级标题，即“主营业务”，该部分不需要二级标题。\n2.本部分的第一段，重点概述目标企业所在细分行业（市场定位）及其提供的产品及服务（主营业务）。如“合肥晶合集成电路股份有限公司处于集成电路晶圆代工行业，其业务主要围绕12英寸晶圆代工展开，为客户提供多种制程工艺节点、多种应用的工艺平台晶圆代工业务和光刻掩模版制造等配套服务。”\n3.之后每段介绍一种产品或服务。对于产品，重点介绍产品的定义、工作原理、特色及差异化特性（优势）、功能用途及应用场景。对于服务，重点介绍服务的内容、范围（如地理范围、生命周期等）、类型（如定制化或标准化，线上或线下等）、价值主张（围绕何种痛点及需求，基于差异化或成本领先等策略）、目标客户、服务场景、商业模式等。\n4.不同产品及服务分不同段落进行介绍。每个段落都不使用标题或序号进行区分。格式上，使用“产品/服务名称+‘。’”的格式展开每一段的论述。这里的关键是，产品和服务名称后使用了句号，之后的内容不分段接在产品词后，不换行。如：“32位通用型MCU。MCU是将中央处理器（CPU）、随机存取存储器（RAM）、只读存储器（ROM）、输入输出端口（I/O）等多种功能集成在一个芯片上的微型计算机系统。其工作原理是通过内部的CPU执行预先存储在ROM中的程序指令，对外部输入信号进行处理，并通过I/O端口输出控制信号。32位通用型MCU具有较高的处理能力和丰富的外设接口。在工业领域，可用于自动化生产线的控制、电机驱动控制、工业机器人的控制等；在汽车电子中，用于车身控制系统、发动机管理系统、安全气囊系统等；在消费类电子中，如智能家电的控制芯片，实现对家电设备的智能化控制；在物联网领域，作为传感器节点的核心控制芯片，负责采集和处理传感器数据，并与网络进行通信。”\n5.确保所介绍的每种产品或服务，严格对应于公司的主营业务，衍生业务或非主营业务不应该作为分析对象。如一家从事肿瘤创新药研发的企业，其工商登记信息中的经营范围还涉及“计算机软硬件及辅助设备批发业务”“货物进出口或技术进出口业务”“软件开发”“企业管理咨询”等业务。这些业务可能与公司的主营业务（创新药物研发）有一些关系，但没有体现在公司对外提供的产品和服务中，那么这些业务都不应作为分析对象，否则不符合本部分“主营业务”的分析目标相悖。\n6.所有的内容生成都不使用序号和标题。如果你希望将不同的部分通过使用标题或者序号进行区分，请将标题或者下级标题放在段首或者句首，然后使用句号，内容跟在句号的后面，不换行。\n7.不引起歧义的情况下，尽可能不分段。确保每一段内容，围绕同一个主题进行内容的生成。内容尽可能详尽，避免每一段只有一两句话的情况。\n8.详细分析和解读材料：认真阅读并理解所提供的相关材料。如材料中未提及某些信息，请通过分析和推理进行补充，以确保报告的完整性。\n9.生成完整、客观的报告：用简明易懂的语言描述企业的各个方面。请确保报告内容详实，逻辑清晰，易于理解。\n10.内容务必求实，中立客观，不做夸大性描述。\n11.内容上与“企业概况”的部分不要重复。\n12.引用和论证：引用相关材料中的具体内容来支持论点。结合材料进行详细说明，增强文本之间的逻辑关联性。\n13.总字数不少于1000字。\n\n##格式要求：\n文本格式化\n1.使用标题（#、##、### ）对不同级别的标题进行区分。\n2.正文段落间需要添加空行，以区分不同段落。\n",

    );

    public function getConfig()
    {
        $result = app('auth')->user() ?? "";
        $admin_id = $result['id'] ?? 1;

        $rst = Db::name("config")->where("admin_id", $admin_id)->select()->toArray();


        if (!$rst) {
            $rst = $this->product_prompt;
        } else {
            $n = [];
            foreach ($rst as $row) {
                $n[$row['name']] = $row['value'];
            }
            $rst = $n;
        }

        return retJson($rst, 200, Db::name("config")->getLastSql());
    }

    public function updateConfig(Request $request)
    {
        $result = app('auth')->user() ?? "";
        $admin_id = $result['id'];
        if (!$admin_id) {
            return retError("请先登录");
        }

        $data = $request->getContent();
        $datas = json_decode($data, true);

        // 开启事务
        Db::startTrans();
        try {
            // 先删除旧的配置
            Db::name("config")->where("admin_id", $admin_id)->delete();

            // 准备插入的新配置数据
            $newConfig = [];
            foreach ($this->product_prompt as $key => $defaultValue) {
                // 使用请求中的数据，如果不存在则使用默认值
                $value = $datas[$key] ?? $defaultValue;
                if (!$value) {
                    $value = $defaultValue;
                }
                $newConfig[$key] = $value;

                Db::name("config")->insert(['name' => $key, 'value' => $value, 'admin_id' => $admin_id]);
            }

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return retError('更新配置失败', $e->getTraceAsString());
        }

        // 返回JSON格式的响应
        return successJson($newConfig);
    }
}
